#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2012 rambla.eu
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.import os
import platform, os, sys, datetime
import json
import unittest
import setup_environ
import raws_json
from raws_json.raws_service import RawsService, Feed, Query
from raws_json.meta.service import MetaService
from raws_json.meta.meta import *
from raws_json.rass.service import RassService

class CrudTest(unittest.TestCase):
    
    @classmethod
    def setUpClass(cls):
        cls.meta_service = MetaService(username = setup_environ.TEST_USERNAME, password = setup_environ.TEST_PASSWORD, server = setup_environ.TEST_SERVER)
        cls.rass_service = RassService(username = setup_environ.TEST_USERNAME, password = setup_environ.TEST_PASSWORD, server = setup_environ.TEST_RASS_SERVER)
        # delete all existing content instances
        feed = cls.meta_service.getContentList()
        mf = Feed(feed)
        for e in mf.entries:
            cls.meta_service.deleteContent(e)
        # make sure files exist on the CDN
        status = cls.rass_service.getItemHeaderFromPath("oze.mp4")
        if status != 200:
            cls.rass_service.postItem(dirpath = "", filename = "oze.mp4", local_path = setup_environ.LOCAL_FILE)
        status = cls.rass_service.getItemHeaderFromPath("oze.webm")
        if status != 200:
            cls.rass_service.postItem(dirpath = "", filename = "oze.webm", local_path = setup_environ.LOCAL_FILE)
        status = cls.rass_service.getItemHeaderFromPath("oze.jpg")
        if status != 200:
            cls.rass_service.postItem(dirpath = "", filename = "oze.jpg", local_path = setup_environ.LOCAL_FILE)
        status = cls.rass_service.getItemHeaderFromPath("aze.mp4")
        if status != 200:
            cls.rass_service.postItem(dirpath = "", filename = "aze.mp4", local_path = setup_environ.LOCAL_FILE)
        status = cls.rass_service.getItemHeaderFromPath("bze.mp4")
        if status != 200:
            cls.rass_service.postItem(dirpath = "", filename = "bze.mp4", local_path = setup_environ.LOCAL_FILE)
        status = cls.rass_service.getItemHeaderFromPath("cze.mp4")
        if status != 200:
            cls.rass_service.postItem(dirpath = "", filename = "cze.mp4", local_path = setup_environ.LOCAL_FILE)
        status = cls.rass_service.getItemHeaderFromPath("test12/one/two/wieze.mp4")
        if status != 200:
            response = cls.rass_service.postItem(dirpath = "test12/one/two/", filename = "wieze.mp4", local_path = setup_environ.LOCAL_FILE)
        status = cls.rass_service.getItemHeaderFromPath("test12/one/two/wieze.webm")
        if status != 200:
            cls.rass_service.postItem(dirpath = "test12/one/two/", filename = "wieze.webm", local_path = setup_environ.LOCAL_FILE)
        status = cls.rass_service.getItemHeaderFromPath("test12/one/two/wieze.jpg")
        if status != 200:
            cls.rass_service.postItem(dirpath = "test12/one/two/", filename = "wieze.jpg", local_path = setup_environ.LOCAL_FILE)
        status = cls.rass_service.getItemHeaderFromPath("test12/one/two/wieze_50.jpg")
        if status != 200:
            cls.rass_service.postItem(dirpath = "test12/one/two/", filename = "wieze_50.jpg", local_path = setup_environ.LOCAL_FILE)
        status = cls.rass_service.getItemHeaderFromPath("test12/one/two/wieze_100.jpg")
        if status != 200:
            cls.rass_service.postItem(dirpath = "test12/one/two/", filename = "wieze_100.jpg", local_path = setup_environ.LOCAL_FILE)

    def setUp(self):
        """ Delete all content for the account before running each test. """
        # delete all existing content instances
        feed = self.meta_service.getContentList()
        mf = Feed(feed)
        for e in mf.entries:
            self.meta_service.deleteContent(e)
    
    def test_create_content__minimal(self):
        """ Create content with only content.name + file set. """
        f = FileObj(path = "oze.mp4")
        mc = MetaContent(name = "ono", file_objs = [f,])
        meta_entry = self.meta_service.createContent(mc.to_entry())
        mc2 = MetaContent(entry = meta_entry)
        for f in mc2.file_objs:
            print f.duration
        # initial content obj must be the same as the one we got back from meta
        self.assertEqual(mc, mc2)
    
    def test_create_content__minimal_with_no_content_name(self):
        """ Create content with only file set => content name should be based on filename. """
        f = FileObj(path = "oze.mp4")
        mc = MetaContent(file_objs = [f,])
        meta_entry = self.meta_service.createContent(mc.to_entry())
        mc2 = MetaContent(entry = meta_entry)
        # the content name is assumed to be "oze"
        self.assertEqual("oze", mc2.name)
        self.assertTrue(mc.compare_file_objs(mc2.file_objs))
    
    def test_create_content__with_meta(self):
        """ Create content with metadata. """
        f = FileObj(path = "oze.mp4", media_type = "video", duration = "33", size = "")
        m = MetaObj(meta_name = "title", vocab = "dc", text = "my bloody valentine", lang = "en")
        mc = MetaContent(name = "ono", file_objs = [f,], tags = ["aap","gaap"], meta_objs = [m,])
        meta_entry = self.meta_service.createContent(mc.to_entry())
        mc2 = MetaContent(entry = meta_entry)
        # initial content obj must be the same as the one we got back from meta
        self.assertEqual(mc, mc2)
    
    def test_create_content__full(self):
        """ Create content with all params + metadata. """
        f = FileObj(path = "/oze.mp4", media_type = "video", duration = 33, size = "", container = "mp4", bitrate = "800", width = "720", height = "360", 
                     frames = "322", framerate = "25", samplerate = "98")
        f2 = FileObj(path = "/oze.jpg")
        m = MetaObj(meta_name = "title", vocab = "dc", text = "my bloody valentine", lang = "en")
        mc = MetaContent(name = "ono", file_objs = [f,f2,], tags = ["aap","gaap"], meta_objs = [m,], thumb_used = "/oze.jpg")
        meta_entry = self.meta_service.createContent(mc.to_entry())
        print unicode(meta_entry)
        mc2 = MetaContent(entry = meta_entry)
        print mc2
        # initial content obj must be the same as the one we got back from meta
        self.assertEqual(mc, mc2)
    
    def test_create_content__using_integers(self):
        """ Create content with all params, but passing integers in the params instead of strings (where applicable). """
        f = FileObj(path = "/oze.mp4", media_type = "video", duration = 33, size = "", container = "mp4", bitrate = 800, width = 720, height = 360, 
                     frames = 322, framerate = 25, samplerate = 98)
        mc = MetaContent(name = "ono", file_objs = [f,], tags = ["aap","gaap"])
        meta_entry = self.meta_service.createContent(mc.to_entry())
        mc2 = MetaContent(entry = meta_entry)
        # self.assertEqual(mc, mc2)
        for f in mc2.file_objs:
            self.assertEqual(f.duration, "33")
            self.assertTrue(f.size)
            self.assertEqual(f.bitrate, "800")
            self.assertEqual(f.width, "720")
            self.assertEqual(f.height, "360")
            self.assertEqual(f.frames, "322")
            self.assertEqual(f.framerate, "25")
            self.assertEqual(f.samplerate, "98")
    
    def test_update_content__params_only(self):
        """ Update only the metadata of a content instance """
        # create initial
        f = FileObj(path = "oze.mp4", media_type = "video", duration = 33, size = "")
        m = MetaObj(meta_name = "title", vocab = "dc", text = "my bloody valentine", lang = "en")
        mc = MetaContent(name = "ono", file_objs = [f,], tags = ["aap","gaap"], meta_objs = [m,])
        meta_entry = self.meta_service.createContent(mc.to_entry())
        # update meta, not files
        f2 = FileObj(path = "oze.mp4", media_type = "video", duration = 22, size = "")
        m2 = MetaObj(meta_name = "title", vocab = "dc", text = "kicking against the pricks", lang = "en")
        mc2 = MetaContent(name = "ono", file_objs = [f2,], tags = ["ef","jef"], meta_objs = [m2,])
        meta_entry = self.meta_service.updateContent(mc2.to_entry())
        mc3 = MetaContent(entry = meta_entry)
        # params.name not changed
        self.assertEqual(mc.name, mc3.name)
        self.assertEqual(mc2.name, mc3.name)
        # params.tags were changed
        self.assertNotEqual(mc.tags, mc3.tags)
        self.assertEqual(mc2.tags, mc3.tags)
        # params.meta was changed
        self.assertFalse(mc.compare_meta_objs(mc3.meta_objs))
        self.assertTrue(mc2.compare_meta_objs(mc3.meta_objs))
        # files were not changed, 'update_files' not set
        self.assertTrue(mc.compare_file_objs(mc3.file_objs))
        self.assertFalse(mc2.compare_file_objs(mc3.file_objs))
    
            
    def test_update_content__files_only(self):
        """ Update only the files of a content instance """
        # create initial
        f1 = FileObj(path = "oze.mp4", media_type = "video", duration = 33, size = "")
        f2 = FileObj(path = "oze.webm", media_type = "video", duration = 33, size = "")
        f3 = FileObj(path = "oze.jpg", media_type = "image", duration = None, size = "")
        m = MetaObj(meta_name = "title", vocab = "dc", text = "my bloody valentine", lang = "en")
        mc = MetaContent(name = "ono", file_objs = [f1,f2,f3], tags = ["aap","gaap"], meta_objs = [m,])
        meta_entry = self.meta_service.createContent(mc.to_entry())
        # check files created
        mc2 = MetaContent(entry = meta_entry)
        self.assertTrue(mc.compare_file_objs(mc2.file_objs))
        # update files
        ff1 = FileObj(path = "test12/one/two/wieze.mp4", media_type = "video", duration = 44, size = "", container = "mp4", bitrate = 800, width = 720, height = 360, 
                     frames = 322, framerate = 25, samplerate = 98)
        ff2 = FileObj(path = "test12/one/two/wieze.webm", media_type = "video", duration = 44, size = "")
        ff3 = FileObj(path = "test12/one/two/wieze.jpg", media_type = "image", duration = None, size = "")
        ff4 = FileObj(path = "test12/one/two/wieze_50.jpg", media_type = "image", duration = None, size = "")
        ff5 = FileObj(path = "test12/one/two/wieze_100.jpg", media_type = "image", duration = None, size = "")
        mc2.file_objs = [ff1,ff2,ff3,ff4,ff5]
        mc2.update_files = 1
        meta_entry = self.meta_service.updateContent(mc2.to_entry())
        mc3 = MetaContent(entry = meta_entry)
        # params.name not changed
        self.assertEqual(mc.name, mc3.name)
        self.assertEqual(mc2.name, mc3.name)
        # params.tags not changed
        self.assertEqual(mc.tags, mc3.tags)
        self.assertEqual(mc2.tags, mc3.tags)
        # params.meta not changed
        self.assertTrue(mc.compare_meta_objs(mc3.meta_objs))
        self.assertTrue(mc2.compare_meta_objs(mc3.meta_objs))
        # files were changed, 'update_files' set
        self.assertFalse(mc.compare_file_objs(mc3.file_objs))
        self.assertTrue(mc2.compare_file_objs(mc3.file_objs))
    
    def test_delete_content(self):
        """ Delete content entry """
        f = FileObj(path = "oze.mp4", media_type = "video", duration = 33, size = "")
        m = MetaObj(meta_name = "title", vocab = "dc", text = "my bloody valentine", lang = "en")
        mc = MetaContent(name = "ono", file_objs = [f,], tags = ["aap","gaap"], meta_objs = [m,])
        meta_entry = self.meta_service.createContent(mc.to_entry())
        self.assertEqual("ono", meta_entry["entry"]["content"]["params"]["name"])
        mc2 = MetaContent(entry = meta_entry)
        self.assertTrue(self.meta_service.deleteContent(mc2.to_entry()))
        
    def test_get_list(self):
        """ Create some content objects and retrieve them back with a GET content request. """
        f1 = FileObj(path = "aze.mp4", media_type = "video", duration = 33, size = "")
        mc1 = MetaContent(name = "ano", file_objs = [f1,], tags = ["aap","gaap"])
        e1 = self.meta_service.createContent(mc1.to_entry())
    
        f2 = FileObj(path = "bze.mp4", media_type = "video", duration = 33, size = "")
        mc2 = MetaContent(name = "bno", file_objs = [f2,], tags = ["oop","goop"])
        e2 = self.meta_service.createContent(mc2.to_entry())
    
        f3 = FileObj(path = "cze.mp4", media_type = "video", duration = 33, size = "")
        mc3 = MetaContent(name = "cno", file_objs = [f3,])
        e3 = self.meta_service.createContent(mc3.to_entry())
    
        feed = self.meta_service.getContentList()
        mf = Feed(feed)
        self.assertEqual(3, len(mf.entries))
        for e in mf.entries:
            mc = MetaContent(entry = e)
            if unicode(mc.name) == unicode("ano"):
                self.assertEqual(mc.name, mc1.name)
                self.assertEqual(mc.tags, mc1.tags)
                self.assertTrue(mc1.compare_file_objs(mc.file_objs))
            elif unicode(mc.name) == unicode("bno"):
                self.assertEqual(mc.name, mc2.name)
                self.assertEqual(mc.tags, mc2.tags)
                self.assertTrue(mc2.compare_file_objs(mc.file_objs))
            elif unicode(mc.name) == unicode("cno"):
                self.assertEqual(mc.name, mc3.name)
                self.assertEqual(mc.tags, mc3.tags)
                self.assertTrue(mc3.compare_file_objs(mc.file_objs))
            else:
                self.assertTrue("test_get_list(): unexpected entry name = %s" % mc.name)
    
    def test_create_fail__no_file_in_body(self):
        """ Try to create content without 'file' object -> fail ! """
        failed = False
        # f = FileObj(path = "oze.mp4", media_type = "video", duration = 33, size = "")
        m = MetaObj(meta_name = "title", vocab = "dc", text = "my bloody valentine", lang = "en")
        mc = MetaContent(name = "ono", tags = ["aap","gaap"], meta_objs = [m,])
        try:
            meta_entry = self.meta_service.createContent(mc.to_entry())
        except Exception, e:
            failed = True
            print str(e)
        self.assertTrue(failed)
       
    def test_create_fail__file_exists(self):
        """ Try to create content with 'file' object that is attached to other Content obj -> fail ! """
        failed = False
        f = FileObj(path = "oze.mp4", media_type = "video", duration = 33, size = "")
        m = MetaObj(meta_name = "title", vocab = "dc", text = "my bloody valentine", lang = "en")
        mc = MetaContent(name = "ono", file_objs = [f,], tags = ["aap","gaap"], meta_objs = [m,])
        meta_entry = self.meta_service.createContent(mc.to_entry())
           
        f2 = FileObj(path = "oze.mp4", media_type = "video", duration = 22, size = "")
        m2 = MetaObj(meta_name = "title", vocab = "dc", text = "kicking against the pricks", lang = "en")
        mc2 = MetaContent(name = "bono", file_objs = [f2,], tags = ["ef","jef"], meta_objs = [m2,])
        try:
            meta_entry = self.meta_service.createContent(mc2.to_entry())
        except Exception, e:
            failed = True
            print str(e)
        self.assertTrue(failed)
    
    def test_update_fail__content_doesnt_exist(self):
        """ Try to send an update request to a content obj that doesn't yet exist. """
        f2 = FileObj(path = "oze.mp4", media_type = "video", duration = 22, size = "")
        m2 = MetaObj(meta_name = "title", vocab = "dc", text = "kicking against the pricks", lang = "en")
        mc2 = MetaContent(name = "bono", file_objs = [f2,], tags = ["ef","jef"], meta_objs = [m2,])
        try:
            meta_entry = self.meta_service.updateContent(mc2.to_entry())
        except Exception, e:
            failed = True
            print str(e)
        self.assertTrue(failed)
    
    def test_delete_fail__content_doesnt_exist(self):
        """ Try to send an update request to a content obj that doesn't yet exist. """
        f = FileObj(path = "oze.mp4", media_type = "video", duration = 33, size = "")
        m = MetaObj(meta_name = "title", vocab = "dc", text = "my bloody valentine", lang = "en")
        mc = MetaContent(name = "ono", file_objs = [f,], tags = ["aap","gaap"], meta_objs = [m,])
        try:
            meta_entry = self.meta_service.deleteContent(mc.to_entry())
        except Exception, e:
            failed = True
            print str(e)
        self.assertTrue(failed)        
        
    def test_search_tags(self):
        f1 = FileObj(path = "aze.mp4", media_type = "video", duration = 33, size = "")
        mc1 = MetaContent(name = "ano", file_objs = [f1,], tags = ["aap","gaap"])
        e1 = self.meta_service.createContent(mc1.to_entry())
    
        f2 = FileObj(path = "bze.mp4", media_type = "video", duration = 33, size = "")
        mc2 = MetaContent(name = "bno", file_objs = [f2,], tags = ["oop","goop"])
        e2 = self.meta_service.createContent(mc2.to_entry())
    
        f3 = FileObj(path = "cze.mp4", media_type = "video", duration = 33, size = "")
        mc3 = MetaContent(name = "cno", file_objs = [f3,])
        e3 = self.meta_service.createContent(mc3.to_entry())
    
        qry = Query()
        qry["tag"] = "goop"
        feed = self.meta_service.getContentList(query = qry)
        mf = Feed(feed)
        self.assertEqual(1, len(mf.entries))
        for e in mf.entries:
            mc = MetaContent(entry = e)
            if unicode(mc.name) == unicode("bno"):
                self.assertEqual(mc.name, mc2.name)
                self.assertEqual(mc.tags, mc2.tags)
                self.assertTrue(mc2.compare_file_objs(mc.file_objs))
            else:
                assertTrue("test_get_list(): unexpected entry name = %s" % mc.name)


def suite():
   suite = unittest.TestSuite()
   suite.addTest(unittest.makeSuite(CrudTest))
   return suite

if __name__=='__main__':
    unittest.main()
